package com.example.designmodel;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;

import com.example.designmodel.bean.CommentInvokeHandler;
import com.example.designmodel.bean.WorkServeceImpl;
import com.example.designmodel.bean.WorkserveiceTwo;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;

public class ProxyActivity extends AppCompatActivity {
    public static void launch(Context context) {
        Intent intent = new Intent(context, ProxyActivity.class);
        context.startActivity(intent);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_proxy);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
//        proxy();
//        dynamic();
        aop();

        //test
//        testStaticProxy();
        testDyProxy();
    }

    private void proxy(){
        IGamePlayer player = new Player("SUNSG");
        IGamePlayer playProxy = new PlayProxy(player);
        playProxy.login("susng","123456");
        playProxy.kileBoss();
        playProxy.update();
//
        IGamePlayer playProxy1 = new PlayProxy("sun");
        playProxy1.login("sun","111111");
        playProxy1.kileBoss();
        playProxy1.update();

        IGamePlayerForce playForce = new PlayForce("guang");
        IGamePlayerForce playProxyForce = (PlayProxyForce) playForce.getProxy();

        playProxyForce.login("GUANG","6543F2F1");
        playProxyForce.kileBoss();
        playProxyForce.update();
    }

    private void dynamic(){
        IGamePlayer player = new Player("guagn");
        InvocationHandler handler = new GamePlayIH(player);
        IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(IGamePlayer.class.getClassLoader(),new Class[]{IGamePlayer.class},handler);
        proxy.login("susng","ddddd");
        proxy.kileBoss();
        proxy.update();
    }

    private void aop(){
        WorkserveiceTwo service = CommentInvokeHandler.getProxyInstance(WorkServeceImpl.class);
        service.doSomething1();
        service.doSomething2(45,56);
    }

    //===============================class=================================
    public static interface IGamePlayer{
        void login(String user,String password);
        void kileBoss();
        void update();
    }

    public static class Player implements IGamePlayer{
        private String name;

        public Player(String name) {
            this.name = name;
        }

        public Player(IGamePlayer player ,String name) throws Exception {
            if(player == null){
                throw new Exception("不能创建真实角色");
            }
            this.name = name;
        }

        @Override
        public void login(String user, String password) {
            Log.i("test","用户名为:"+user+"的用户"+name +"登录成功");
        }

        @Override
        public void kileBoss() {
            Log.i("test",name +"在打怪");
        }

        @Override
        public void update() {
            Log.i("test",name +"升级了");
        }
    }


    public static class PlayProxy implements IGamePlayer{
        private IGamePlayer player;

        public PlayProxy(IGamePlayer player) {
            this.player = player;
        }

        public PlayProxy(String name){
            try {
                player = new Player(this,name);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void login(String user, String password) {
            player.login(user,password);
        }

        @Override
        public void kileBoss() {
            player.kileBoss();
        }

        @Override
        public void update() {
            player.update();
        }
    }

    //================================dynamic====================================

    public static class GamePlayIH implements InvocationHandler{
        /**被代理的实例*/
        private Object obj = null;

        /**
         * 我要代理谁
         * @param obj
         */
        public GamePlayIH(Object obj) {
            this.obj = obj;
        }
        //调用被代理的方法
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            return method.invoke(obj,args);
        }
    }


    //=================================force proxy===============================
    public static interface IGamePlayerForce{
        void login(String user,String password);
        void kileBoss();
        void update();
        IGamePlayerForce getProxy();
    }

    public static class PlayForce implements IGamePlayerForce{
        private IGamePlayerForce proxyForce;
        private String name;

        public PlayForce(String name) {
            this.name = name;
        }

        @Override
        public void login(String user, String password) {
            if(isProxy()){
                Log.i("test","用户名为:"+user+"的用户"+name +"登录成功");
            }else{
                Log.i("test","请使用指定的代理访问");
            }

        }

        @Override
        public void kileBoss() {
            if(isProxy()){
                Log.i("test",name +"在打怪");
            }else{
                Log.i("test","请使用指定的代理访问");
            }
        }

        @Override
        public void update() {
            if(isProxy()){
                Log.i("test",name +"升级了");
            }else{
                Log.i("test","请使用指定的代理访问");
            }
        }

        @Override
        public IGamePlayerForce getProxy() {
            return proxyForce = new PlayProxyForce(this);

        }

        private boolean isProxy(){
            if(proxyForce == null){
                return false;
            }else{
                return true;
            }
        }

    }

    public static class PlayProxyForce implements IGamePlayerForce{
        private IGamePlayerForce playerForce;

        public PlayProxyForce(IGamePlayerForce playerForce) {
            this.playerForce = playerForce;
        }

        @Override
        public void login(String user, String password) {
            playerForce.login(user,password);
        }

        @Override
        public void kileBoss() {
            playerForce.kileBoss();
        }

        @Override
        public void update() {
            playerForce.update();
        }

        @Override
        public IGamePlayerForce getProxy() {
            //代理的代理暂时还没有，就是自己
            return this;
        }
    }

    //======================AOP===================================

//    public static class LogInvoHandler implements InvocationHandler {
//        private Object target;//代理目标
//        private Object proxy;//代理对象
//
//        public static <T> T getPorxyInstance(Class<T> calzz) {
//            LogInvoHandler handler = new LogInvoHandler();
//            try {
//                T targetObject = calzz.newInstance();
//                handler.setTarget(targetObject);
//                Object proxy = Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), handler);
//                handler.setProxy(proxy);
//            } catch (InstantiationException e) {
//                e.printStackTrace();
//            } catch (IllegalAccessException e) {
//                e.printStackTrace();
//            }
//
//            return (T) handler.getProxy();
//        }
//
//        @Override
//        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//            Object result = method.invoke(target, args);
//            Log.i("test", "_invoke method :" + method.getName() + "\r\n"
//                    + "args : " + (null == args ? "null" : Arrays.asList(args).toString() + "\r\n")
//                    + "result : " + result
//            );
//            return result;
//        }
//
//        public Object getTarget() {
//            return target;
//        }
//
//        public void setTarget(Object target) {
//            this.target = target;
//        }
//
//        public Object getProxy() {
//            return proxy;
//        }
//
//        public void setProxy(Object proxy) {
//            this.proxy = proxy;
//        }
//    }
//
//    public interface WorkServece{
//        void doSomething1();
//        void doSomething2(int yuan,float fen);
//    }
//
//    public class WorkServeceImpl implements WorkServece{
//
//        public WorkServeceImpl() {
//        }
//
//        @Override
//        public void doSomething1() {
//            Log.i("test","doSomething1");
//        }
//
//        @Override
//        public void doSomething2(int yuan, float fen) {
//            Log.i("test","doSomething2 "+ yuan +" "+fen);
//        }
//    }

    //==================================================== test static Proxy ==========================================

    interface Shopping{
        Object[] doShopping(long money);
    }

    class ShoppingImpl implements Shopping{

        @Override
        public Object[] doShopping(long money) {
            Object[] oo = new Object[]{"衣服","鞋子","袜子"};
            Log.i("test","花了"+money+"钱"+"买了 "+ Arrays.toString(oo));
            return oo;
        }
    }

    class ShoppingProxy implements Shopping{
        private Shopping shopping;

        public ShoppingProxy(Shopping shopping) {
            this.shopping = shopping;
        }

        @Override
        public Object[] doShopping(long money) {
            Object[] oo = this.shopping.doShopping(money);
            oo[0] = "皮带";
            Log.i("test","花了"+money+"钱"+"买了 "+ Arrays.toString(oo));
            return oo;
        }
    }

    private void testStaticProxy(){
        //自己买东西
        Shopping shopping = new ShoppingImpl();
        shopping.doShopping(100);

        //招代理
        Shopping proxy = new ShoppingProxy(shopping);
        proxy.doShopping(100);
    }

    private void testDyProxy(){
        Shopping shopping = new ShoppingImpl();
        Shopping shopping2 = (Shopping) Proxy.newProxyInstance(shopping.getClass().getClassLoader(),shopping.getClass().getInterfaces(),new ShoppingInvocationHandler(shopping));
        shopping2.doShopping(100);
        Log.i("test","proxy.tostring daili = "+ shopping2.toString());
    }

    class ShoppingInvocationHandler implements InvocationHandler{
        private Shopping shopping;
        public ShoppingInvocationHandler(Shopping shopping) {
            this.shopping = shopping;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            if ("doShopping".equals(method.getName())) {
                Log.i("test","invoke");
                if(proxy == null){
                    Log.i("test","proxy = null");
                }else{
                    Log.i("test","proxy.tostring = "+ proxy.toString());
                }

                Log.i("test","target.tostring = "+ shopping.toString());
                // 这里是代理Shopping接口的对象

                // 先黑点钱(修改输入参数)
                Long money = (Long) args[0];
                long readCost = (long) (money * 0.5);

                System.out.println(String.format("花了%s块钱", readCost));

                // 帮忙买东西
                Object[] things = (Object[]) method.invoke(shopping, readCost);

                // 偷梁换柱(修改返回值)
                if (things != null && things.length > 1) {
                    things[0] = "被掉包的东西!!";
                }
                Log.i("test","花了"+money+"钱"+"买了 "+ Arrays.toString(things));
                return things;
            }
            return method.invoke(shopping,args);
        }


    }


}
